import 'dart:ui';

///链式执行代码块。
///方法调用用顺序[onOpen]||[onClose]||[add]->[execute]->如需要手动停止则调用[stop]。
///[onOpen]||[onClose]||[add]必须在[execute]之前调用。
///[add]可多次调用添加任务，遵循先进先出的原则。
///调用[execute]时会回调[onOpen]。
///无论是自动停止或者手动停止，都会调用[onClose]。
class ChainExecutor {
  ///单例处理
  ChainExecutor._internal();

  factory ChainExecutor() => _instance;
  static final ChainExecutor _instance = ChainExecutor._internal();

  ///是否开启了执行线程
  bool _isOpen = false;

  ///执行队列
  final List<Chain> _queueChain = [];

  VoidCallback? _closeCallBack;
  VoidCallback? _openCallBack;

  Chain? _tempChain;
  dynamic _tempData;

  ///开启执行线程
  onOpen(VoidCallback openCallBack) {
    _openCallBack = openCallBack;
  }

  ///所有任务执行完成关闭执行线程
  onClose(VoidCallback closeCallBack) {
    _closeCallBack = closeCallBack;
  }

  ///添加需要执行的任务到执行线程
  add(Chain chain) {
    _queueChain.add(chain);
  }

  ///添加一组需要执行的任务到执行线程
  addAll(List<Chain> chains) {
    _queueChain.addAll(chains);
  }

  ///如果当前的Chain处于等待状态，没有主动调用结束，
  ///可以外部介入调用[next]主动结束当前的Chain执行下一个Chain。
  ///注意，如果当前Chain处于等待状态，且还有异步任务在执行，
  ///主动调用[next]，会导致执行的异步任务脱离链式执行状态，
  ///不再继续等待该任务执行完，会直接进入到下一个Chain的执行。
  ///[data]为给下一个Chain传递的参数，
  ///如果当前的Chain传递了参数，
  ///则以此处的[data]为准，因为[data]会替换Chain传递的参数。
  next({dynamic data}) {
    if (data != null) {
      _tempData = data;
    }
    _tempChain?.finish();
  }

  ///开始执行。
  ///如果没有调用[add]||[addAll]添加数据，也可以直接在这里添加添加一条[Chain]
  execute({Chain? chain}) {
    if (chain != null) {
      _queueChain.add(chain);
    }
    _isOpen = true;
    _openCallBack?.call();
    _executor().then((value) {
      if (value) {
        _closeCallBack?.call();
        _tempChain = null;
        _tempData = null;
      }
    });
  }

  ///主动停止。
  ///终止执行。
  ///界面退出时如果链中还有任务没执行完成需要调用该方法，否者会内存溢出。
  stop() {
    _isOpen = false;
  }

  Future<bool> _executor() async {
    return Future(() async {
      while (_isOpen) {
        if (_isOpen) {
          if (_queueChain.isNotEmpty &&
              (_tempChain == null || _tempChain!.isFinished())) {
            _tempChain = _queueChain.removeAt(0);
            if (!_tempChain!.isFinished()) {
              _tempChain!.execute(_tempData);
              _tempData = _tempChain!.data;
            }
          }
        }
        //退出条件
        if ((!_isOpen) ||
            (_isOpen &&
                _queueChain.isEmpty &&
                (_tempChain == null || _tempChain!.isFinished()))) {
          break;
        }
        await Future.delayed(const Duration(milliseconds: 50));
      }
      return true;
    });
  }
}

///执行一些代码，不管是异步还是同步，执行完成后调用[Chain]的[finish]方法才会执行下一个[Chain]。
class Chain {
  dynamic data;

  final dynamic Function(Chain chain, dynamic data) callback;

  Chain(this.callback);

  ///任务是否执行完毕。
  ///创建[Chain]相当于就开启了一个无限循环的任务一直等待该任务执行完毕，
  ///用户需要在任务完成时主动调用[finish]结束任务。
  bool _finished = false;

  ///用户任务实际执行的方法
  execute(dynamic data) {
    this.data = callback.call(this, data);
  }

  ///用户主动结束任务执行
  finish() {
    _finished = true;
  }

  isFinished() {
    return _finished;
  }
}

/// 测试类
class Test {
  test() {
    ChainExecutor executor = ChainExecutor();
    executor
      ..onOpen(() {
        ///执行前做什么事情
      })
      ..onClose(() {
        ///执行完毕做什么事情
      })
      ..add(Chain((chain, data) {
        ///do some thing
        ///执行一些代码，不管是异步还是同步，执行完成后调用[Chain]的[finish]方法才会执行下一个[Chain]
        ///可以往下一个Chain传递参数调用[Chain]中的[sendData]
        ///或者可以接收上一个Chain传递过来的参数调用[Chain]中的[receiveData]
      }))
      ..add(Chain((chain, data) {
        ///do some thing
      }))
      ..execute();
    executor.next(data: "我是主动结束当前Chain给下一个Chain传递的参数");
    executor.stop();
  }
}
